package com.dmz.workflow.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.dmz.workflow.dao.ApprovalNodeMapper;
import com.dmz.workflow.entity.*;
import com.dmz.workflow.entity.Dictionary;
import com.dmz.workflow.req.ListQuery;
import com.dmz.workflow.service.*;
import com.dmz.workflow.util.*;
import com.dmz.workflow.vo.*;
import com.dmz.workflow.wrapper.MemberFeignWrapper;
import com.echronos.commons.Result;
import com.echronos.commons.enums.ErrorMsgEnum;
import com.echronos.commons.model.RequestUser;
import com.echronos.commons.utils.RequestUserUtils;
import com.echronos.system.feign.IMemberFeign;
import com.echronos.system.resp.MemberResp;
import com.echronos.system.resp.member.MemberDetailsResp;
import com.echronos.workflow.entity.*;
import com.echronos.workflow.service.*;
import com.echronos.workflow.util.*;
import com.echronos.workflow.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.editor.language.json.converter.util.CollectionUtils;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service
@Transactional(rollbackFor = Exception.class)
public class FlowableTaskServiceImpl implements FlowableTaskService {
    @Autowired
    protected IdentityService identityService;

    @Autowired
    protected RepositoryService repositoryService;

    @Autowired
    protected TaskService taskService;

    @Autowired
    protected RuntimeService runtimeService;

    @Autowired
    protected HistoryService historyService;

    @Autowired
    protected PermissionServiceImpl permissionService;

    @Autowired
    protected ManagementService managementService;

    @Autowired
    protected FormService formService;

    @Resource
    private ImcComponent imcComponent;

    @Autowired
    private MemberFeignWrapper memberFeignWrapper;

    @Autowired
    private WorkflowNodeInfoService workflowNodeInfoService;

    @Autowired
    private WorkflowNodeExtService workflowNodeExtService;

    @Autowired
    private WorkflowProcessJsonService workflowProcessJsonService;

    @Autowired
    private WorkflowProcessStatusService workflowProcessStatusService;

    @Autowired
    private WorkflowDiscussionService workflowDiscussionService;

    @Autowired
    private WorkflowDictionaryService workflowDictionaryService;

    @Autowired
    private ApprovalNodeMapper approvalNodeMapper;

    @Autowired
    private MessageContentWrapper messageContentWrapper;

    @Autowired
    private IMemberFeign memberFeign;

    private TaskEntity operatorTaskEntity;

    @Autowired
    private CommonMessageManager commonMessageManager;

    @Autowired
    private WorkflowProcessRelationsService workflowProcessRelationsService;

    @Autowired
    private WorkflowFormDataService workflowFormDataService;

    @Autowired
    private CallBackComponent callBackComponent;

    /**
     * 转办
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> assignTask(DelegateReq delegateReq) {
        return processDelegateAndTransfer(delegateReq, ProcessConstants.PERSON_TRANSFER_STATUS);
    }

    /**
     * 委派任务
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> delegateTask(DelegateReq delegateReq) {
        return processDelegateAndTransfer(delegateReq, ProcessConstants.PERSON_DELEGATE_STATUS);
    }

    protected void processNodeExtData(String comment, Task task, Integer status, String targetMemberId, boolean updateStatus) {
        StaffInfo staffInfoTem = new StaffInfo();
        staffInfoTem.setProcessInstanceId(task.getProcessInstanceId());
        staffInfoTem.setIdNode(task.getTaskDefinitionKey());
        staffInfoTem.setComment(comment);
        staffInfoTem.setTaskId(task.getId());
        staffInfoTem.setStatus(status);
        if (task.getTaskDefinitionKey().contains(ProcessDefinitionConstants.CHECK_NODE)) {
            staffInfoTem.setTypeNode(ProcessDefinitionConstants.CHECK_NODE);
        }
        staffInfoTem.setMemberId(RequestUserUtils.getUser().getMemberId());
        if (ObjectUtils.isNotEmpty(targetMemberId)) {
            staffInfoTem.setTargetMemberId(targetMemberId);
        }
        if (updateStatus) {
            workflowNodeExtService.updateNodeExtByProcessInstanceIdAndNodeId(staffInfoTem);
            // 处理审批后节点的任务ID
            List<Task> currentTasks = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
            List<StaffInfo> staffInfos = new ArrayList<>();
            StaffInfo staffInfo;
            for (Task currentTask : currentTasks) {
                if (StringUtils.isNotEmpty(currentTask.getAssignee())) {
                    staffInfo = new StaffInfo();
                    staffInfo.setProcessInstanceId(currentTask.getProcessInstanceId());
                    staffInfo.setMemberId(Integer.valueOf(currentTask.getAssignee()));
                    staffInfo.setIdNode(currentTask.getTaskDefinitionKey());
                    staffInfo.setTaskId(currentTask.getId());
                    staffInfos.add(staffInfo);
                }
            }
            if (ObjectUtils.isNotEmpty(staffInfos)) {
                workflowNodeExtService.updateBatchTaskId(staffInfos);
            }
        } else {
            workflowNodeExtService.save(staffInfoTem);
        }
    }

    /**
     * 提交任务
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> completeTask(CompleteReq completeReq) {
        String taskId = completeReq.getTaskId();
        String curMemberId = String.valueOf(RequestUserUtils.getUser().getMemberId());
        //获取任务节点结果
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        String processInstanceId = task.getProcessInstanceId();
        Map<String, Object> completeVariables = null;
        // 非会签用户节点，默认设置流程变量 __taskDefinitionKey__=currUserId，用于存储该节点执行人，且以最近的执行人为准
        Process process = repositoryService.getBpmnModel(task.getProcessDefinitionId()).getMainProcess();
        UserTask userTask = (UserTask) process.getFlowElement(task.getTaskDefinitionKey(), true);
        if (userTask != null && !userTask.hasMultiInstanceLoopCharacteristics()) {
            completeVariables = new HashMap<>(1);
            completeVariables.put("__" + task.getTaskDefinitionKey() + "__", curMemberId);
        }
        if (task.getAssignee() == null || !task.getAssignee().equals(curMemberId)) {
            taskService.setAssignee(taskId, curMemberId);
        }
        if (ObjectUtils.isEmpty(task.getParentTaskId())) {
            // 判断是否是协办完成还是正常流转
            if (DelegationState.PENDING.equals(task.getDelegationState())) {
                taskService.resolveTask(taskId, completeVariables);
                // 如果当前执行人是任务所有人，直接完成任务
                if (curMemberId.equals(task.getOwner())) {
                    taskService.complete(taskId, completeVariables);
                }
            } else {
                taskService.complete(taskId, completeVariables);
            }
        } else {
            // 处理加签节点信息
            String parentTaskId = task.getParentTaskId();
            String tableName = managementService.getTableName(TaskEntity.class);
            String sql = "select count(1) from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId}";
            long subTaskCount = taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).count();
            if (subTaskCount == 0) {
                Task parentTask = taskService.createTaskQuery().taskId(parentTaskId).singleResult();
                if (ObjectUtils.isNotEmpty(parentTask)) {
                    taskService.complete(parentTaskId);
                }
            } else {
                if (DelegationState.PENDING.equals(task.getDelegationState())) {
                    taskService.resolveTask(taskId, completeVariables);
                } else {
                    taskService.complete(taskId, completeVariables);
                }
                if (subTaskCount == 1) {
                    taskService.complete(parentTaskId);
                }
            }
        }
        List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        for (Task tempTask : list) {
            if (ObjectUtils.isNotEmpty(tempTask.getAssignee()) && tempTask.getAssignee().equals(curMemberId) && task.getTaskDefinitionKey().equals(tempTask.getTaskDefinitionKey())) {
                taskService.complete(tempTask.getId());
            }
        }
        processNodeArriveAndTaskIdStatus(processInstanceId, task.getTaskDefinitionKey(), taskId);
        processNodeExtData(completeReq.getMessage(), task, ProcessConstants.PERSON_APPROVED_STATUS, null, true);
        if (ObjectUtils.isNotEmpty(completeReq.getDictionaryVOList())) {
            saveApproveAttachments(completeReq.getDictionaryVOList(), processInstanceId, completeReq.getProcessNodeId());
        }
        if (ObjectUtils.isNotEmpty(completeReq.getAtPersons())) {
            Result<MemberResp> memberById = memberFeignWrapper.getMemberById(RequestUserUtils.getUser().getMemberId());
            imcComponent.imcAssistantSender(
                    messageContentWrapper.generateCommentMessageBody(MsgContentEnum.MESSAGE_COMMENT_CONTENT, task.getProcessInstanceId(), memberById.getData().getName()),
                    RequestUserUtils.getUser().getId(), completeReq.getAtPersons(), null
            );
            workflowProcessRelationsService.save(ProcessRelations.builder().processInstanceId(processInstanceId).userIds(StringUtils.join(completeReq.getAtPersons(), LanguageExpressionConstants.LANGUAGE_COMMA)).build());
        }
        ConcurrentHashMap<String, String> processInstanceStatusData = TemporaryStatus.getInstance().getProcessInstanceStatusData();
        processInstanceStatusData.put(processInstanceId, processInstanceId);
        commonMessageManager.sendAssistantMessageByProcessInstanceId(processInstanceId);
        return Result.build();
    }

    private void processNodeArriveAndTaskIdStatus(String processInstanceId, String taskDefinitionKey, String taskId) {
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        boolean isFinished = true;
        String currentTaskId = null;
        for (Task task : tasks) {
            if (task.getTaskDefinitionKey().equals(taskDefinitionKey)) {
                currentTaskId = task.getId();
                isFinished = false;
                break;
            }
        }
        workflowNodeInfoService.updateNodeTaskIdStatus(processInstanceId, taskDefinitionKey, isFinished ? taskId : currentTaskId, isFinished ? ProcessConstants.NODE_ARRIVED_STATUS : null);
        if (isFinished) {
            for (Task task : tasks) {
                workflowNodeInfoService.updateNodeArriveStatus(processInstanceId, task.getTaskDefinitionKey(), null, task.getId(), ProcessConstants.NODE_ARRIVE_STATUS);
                break;
            }
        }
    }

    /**
     * 暂停任务
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> refuseTask(CompleteReq completeReq) {
        String taskId = completeReq.getTaskId();
        String memberId = String.valueOf(RequestUserUtils.getUser().getMemberId());
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            return Result.build(ErrorMsgEnum.NORMAL_ERR.getErrorCode(), ExceptionMessageConstants.TASK_ID_NOT_EXIST);
        }
        ProcessInstance processInstance =
                runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        if (processInstance == null) {
            return Result.build(ErrorMsgEnum.NORMAL_ERR.getErrorCode(), ExceptionMessageConstants.PROCESS_INSTANCE_ID_NOT_EXIST);
        }
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        if (bpmnModel != null) {
            Process process = bpmnModel.getMainProcess();
            List<EndEvent> endNodes = process.findFlowElementsOfType(EndEvent.class, false);
            String processInstanceId = processInstance.getProcessInstanceId();
            ProcessInstanceStatus processInstanceStatus = workflowProcessStatusService.selectInstanceByInstanceId(processInstanceId);
            // 圈层价审批驳回回调通知listener消息
            if (ObjectUtils.isNotEmpty(processInstanceId) && ProcessConstants.PROCESS_INSTANCE_CIRCLE_PRICE_TYPE.equals(processInstanceStatus.getProcessInstanceType())) {
                ConcurrentHashMap<String, String> processInstanceStatusData = new ConcurrentHashMap<>();
                processInstanceStatusData.put(processInstanceId,"2");
                TemporaryStatus.getInstance().setProcessInstanceStatusData(processInstanceStatusData);
            }
            if (endNodes != null && endNodes.size() > 0) {
                String endId = endNodes.get(0).getId();
                List<Execution> executions =
                        runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list();
                List<String> executionIds = new ArrayList<>();
                executions.forEach(execution -> executionIds.add(execution.getId()));
                runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds,
                        endId).changeState();
                workflowProcessStatusService.updateStatusByProcessInstanceId(processInstance.getProcessInstanceId(), ProcessConstants.PROCESS_REFUSE_STATUS);
                workflowNodeExtService.updateNodeExtByProcessInstanceIdAndNodeId(getStaffUpdateInfo(processInstance.getProcessInstanceId(), ProcessConstants.PERSON_REFUSE_STATUS, memberId, task.getTaskDefinitionKey(), completeReq.getMessage()));
                workflowNodeInfoService.updateNodeTaskIdCaseRefuseOperation(processInstance.getProcessInstanceId(), task.getTaskDefinitionKey(), task.getId());
                workflowNodeInfoService.updateNodeCaseRefuseOperation(processInstance.getProcessInstanceId());
                workflowNodeExtService.updateNodeExtCaseRefuseOperation(processInstance.getProcessInstanceId());
                if (ObjectUtils.isNotEmpty(completeReq.getDictionaryVOList())) {
                    saveApproveAttachments(completeReq.getDictionaryVOList(), processInstance.getProcessInstanceId(), completeReq.getProcessNodeId());
                }
                // 圈层价审批驳回回调
                if (ObjectUtils.isNotEmpty(processInstanceId) && ProcessConstants.PROCESS_INSTANCE_CIRCLE_PRICE_TYPE.equals(processInstanceStatus.getProcessInstanceType())) {
                    callBackComponent.circlePriceCallBack(processInstanceId, ProcessConstants.PERSON_REFUSE_STATUS, completeReq.getMessage());
                }
            }
        }
        MemberDetailsResp memberDetailsResp = memberFeign.queryMemberById(Integer.valueOf(processInstance.getStartUserId()));
        imcComponent.imcAssistantSender(
                messageContentWrapper.generateNotCommentMessageBody(MsgContentEnum.MESSAGE_REFUSE_COMMENT, task.getProcessInstanceId()),
                RequestUserUtils.getUser().getId(),
                Collections.singletonList(memberDetailsResp.getUserId()), null);
        return Result.build();
    }

    @Override
    public void repealTask(CompleteReq completeReq) {
        String taskId = completeReq.getTaskId();
        String memberId = String.valueOf(RequestUserUtils.getUser().getMemberId());
        ProcessInstance processInstance = permissionService.validateStopProcessInstancePermissionOnTask(taskId, memberId);
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        if (bpmnModel != null) {
            Process process = bpmnModel.getMainProcess();
            List<EndEvent> endNodes = process.findFlowElementsOfType(EndEvent.class, false);
            if (endNodes != null && endNodes.size() > 0) {
                String endId = endNodes.get(0).getId();
                List<Execution> executions =
                        runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list();
                List<String> executionIds = new ArrayList<>();
                executions.forEach(execution -> executionIds.add(execution.getId()));
                runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds,
                        endId).changeState();
                workflowProcessStatusService.updateStatusByProcessInstanceId(processInstance.getProcessInstanceId(), ProcessConstants.PROCESS_REVOCATION_STATUS);
                String processInstanceId = processInstance.getProcessInstanceId();
                workflowNodeInfoService.updateRepealProcessNode(processInstanceId);
                workflowNodeInfoService.save(getIntermediateRepealNodeInfo(processInstanceId));
                workflowNodeExtService.save(getStaffSaveInfo(processInstanceId, ProcessConstants.PERSON_REPEAL_STATUS, memberId, completeReq.getMessage()));
                if (ObjectUtils.isNotEmpty(completeReq.getDictionaryVOList())) {
                    saveApproveAttachments(completeReq.getDictionaryVOList(), processInstance.getProcessInstanceId(), completeReq.getProcessNodeId());
                }
            }
        }
        MemberDetailsResp memberDetailsResp = memberFeign.queryMemberById(Integer.valueOf(processInstance.getStartUserId()));
        imcComponent.imcAssistantSender(
                messageContentWrapper.generateNotCommentMessageBody(MsgContentEnum.MESSAGE_REPEAL_CONTENT, processInstance.getProcessInstanceId()),
                RequestUserUtils.getUser().getId(),
                Collections.singletonList(memberDetailsResp.getUserId()), null);
    }

    @Override
    public List<IntermediateNodeVo> queryReachableBackNodes(String processInstanceId) {
        List<IntermediateNode> intermediateNodes = workflowNodeInfoService.queryReachableBackNodes(processInstanceId);
        List<IntermediateNodeVo> intermediateNodeVos = null;
        if (!ObjectUtils.validateCollectionIsEmpty(intermediateNodes)) {
            List<String> nodeIds = new ArrayList<>();
            for (IntermediateNode intermediateNode : intermediateNodes) {
                nodeIds.add(intermediateNode.getNodeId());
            }
            intermediateNodeVos = BeanUtilsExt.copyObjectListProperties(intermediateNodes, IntermediateNodeVo.class);
            List<StaffInfo> staffInfos = workflowNodeExtService.selectListByProcessInstanceIdAndNodeId(processInstanceId, nodeIds);
            if (!ObjectUtils.validateCollectionIsEmpty(staffInfos)) {
                List<StaffInfoVo> staffInfoVoList;
                StaffInfoVo staffInfoVo;
                for (IntermediateNodeVo intermediateNodeVo : intermediateNodeVos) {
                    staffInfoVoList = new ArrayList<>();
                    for (StaffInfo staffInfo : staffInfos) {
                        if (intermediateNodeVo.getNodeId().equals(staffInfo.getIdNode())) {
                            staffInfoVo = new StaffInfoVo();
                            BeanUtils.copyProperties(staffInfo, staffInfoVo);
                            staffInfoVoList.add(staffInfoVo);
                        }
                    }
                    intermediateNodeVo.setStaffInfoList(staffInfoVoList);
                }
            }
        }
        return intermediateNodeVos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void backTask(BackReq backReq) {
        String taskId = backReq.getTaskId();
        String memberId = String.valueOf(RequestUserUtils.getUser().getMemberId());
        Task task = permissionService.validateExcutePermissionOnTask(taskId, memberId);
        String processInstanceId = task.getProcessInstanceId();
        runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(processInstanceId)
                .moveActivityIdTo(task.getTaskDefinitionKey(), backReq.getActivityId())
                .changeState();
        StaffInfo staffInfo = new StaffInfo();
        staffInfo.setProcessInstanceId(task.getProcessInstanceId());
        staffInfo.setIdNode(task.getTaskDefinitionKey());
        staffInfo.setStatus(ProcessConstants.PERSON_REJECT_STATUS);
        staffInfo.setComment(backReq.getMessage());
        staffInfo.setMemberId(RequestUserUtils.getUser().getMemberId());
        workflowNodeExtService.updateNodeExtByProcessInstanceIdAndNodeId(staffInfo);
        if (!ObjectUtils.validateCollectionIsEmpty(backReq.getDictionaryVOList())) {
            saveApproveAttachments(backReq.getDictionaryVOList(), processInstanceId, task.getTaskDefinitionKey());
        }
        Integer start = backReq.getSrcSort();
        Integer end = backReq.getTarSort();
        String startNodeId = "";
        int interval = 0;
        // 查询开始退回节点之后的所有节点信息
        List<IntermediateNode> intermediateNodes = workflowNodeInfoService.queryBackNodes(processInstanceId, end);
        // 复制节点信息
        List<IntermediateNode> tempIntermediateNodes = BeanUtilsExt.copyObjectListProperties(intermediateNodes, IntermediateNode.class);
        String nodeTitle = "";
        for (IntermediateNode intermediateNode : intermediateNodes) {
            if (intermediateNode.getSort().equals(end)) {
                startNodeId = intermediateNode.getNodeId();
            }
            // 过滤已经是退回的节点，计算实际退回节点的数量
            if (intermediateNode.getSort() <= start && !ProcessDefinitionConstants.BACK_NODE.equals(intermediateNode.getNodeType())) {
                interval++;
            }
            if (intermediateNode.getSort().equals(end)) {
                nodeTitle = intermediateNode.getNodeTitle();
            }
        }
        int nodeAfterBack = start + interval;
        List<String> nodeIds = new ArrayList<>();
        int backNum = workflowNodeInfoService.queryBackNodesNum(processInstanceId);
        int backIndex = backNum;
        for (IntermediateNode intermediateNode : intermediateNodes) {
            if (intermediateNode.getSort() <= start) {
                // 1.更新开始退回节点到退回节点之间的节点状态（置灰显示）
                nodeIds.add(intermediateNode.getNodeId());
                String newNodeId = ProcessDefinitionConstants.BACK_NODE + "_" + ++backIndex;
                workflowDiscussionService.updateBackDiscussion(processInstanceId, intermediateNode.getNodeId(), newNodeId);
                workflowDictionaryService.updateBackDictionary(processInstanceId, intermediateNode.getNodeId(), newNodeId);
                intermediateNode.setNodeId(newNodeId);
                intermediateNode.setNodeType(ProcessDefinitionConstants.BACK_NODE);
                intermediateNode.setIsArrive(ProcessConstants.NODE_ARRIVED_STATUS);
            } else {
                // 2.更新开始退回节点之后的节点顺序
                intermediateNode.setSort(++nodeAfterBack);
            }
        }
        workflowNodeInfoService.updateBatchById(intermediateNodes);

        Integer newIndex = start;
        List<IntermediateNode> newIntermediateNodes = new ArrayList<>();
        for (int i = 0; i < tempIntermediateNodes.size(); i++) {
            if (tempIntermediateNodes.get(i).getSort() <= start) {
                tempIntermediateNodes.get(i).setSort(++newIndex);
                if (i == 0) {
                    tempIntermediateNodes.get(i).setIsArrive(ProcessConstants.NODE_ARRIVE_STATUS);
                } else {
                    tempIntermediateNodes.get(i).setIsArrive(ProcessConstants.NODE_NOT_ARRIVE_STATUS);
                }
                newIntermediateNodes.add(tempIntermediateNodes.get(i));
            }
        }
        workflowNodeInfoService.saveBatch(newIntermediateNodes);
        Set<Integer> backNodeMemberIds = new HashSet<>();
        List<StaffInfo> staffInfos = workflowNodeExtService.selectListByProcessInstanceIdAndNodeId(processInstanceId, nodeIds);
        List<StaffInfo> newStaffInfos = BeanUtilsExt.copyObjectListProperties(staffInfos, StaffInfo.class);
        // 更新原节点的节点类型
        backIndex = backNum;
        for (IntermediateNode newIntermediateNode : tempIntermediateNodes) {
            backIndex++;
            for (StaffInfo info : staffInfos) {
                if (info.getMemberId().equals(Integer.valueOf(memberId)) && info.getIdNode().equals(newIntermediateNode.getNodeId()) && newIntermediateNode.getSort().equals(newIndex)) {
                    info.setTargetNodeTitle(nodeTitle);
                }
                if (info.getIdNode().equals(newIntermediateNode.getNodeId())) {
                    info.setIdNode(ProcessDefinitionConstants.BACK_NODE + "_" + backIndex);
                    info.setTypeNode(ProcessDefinitionConstants.BACK_NODE);
                }
            }
        }
        workflowNodeExtService.updateBatchById(staffInfos);

        List<Task> taskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
        List<StaffInfo> staffInfoList = new ArrayList<>();
        // 过滤委派节点
        for (StaffInfo transferStaffInfo : newStaffInfos) {
            if (ProcessConstants.PERSON_TRANSFER_STATUS.equals(transferStaffInfo.getStatus())) {
                staffInfoList.add(transferStaffInfo);
            }
        }
        // 复制节点类型
        List<StaffInfo> newStaffInfoData = new ArrayList<>();
        for (StaffInfo newStaffInfo : newStaffInfos) {
            if (newStaffInfo.getIdNode().equals(startNodeId)) {
                backNodeMemberIds.add(newStaffInfo.getUserId());
            }
            boolean transferFlag = false;
            for (StaffInfo transferStaffInfo : staffInfoList) {
                if (transferStaffInfo.getIdNode().equals(newStaffInfo.getIdNode()) && transferStaffInfo.getTargetMemberId().equals(String.valueOf(newStaffInfo.getMemberId()))) {
                    transferFlag = true;
                    break;
                }
            }
            if (!transferFlag) {
                StaffInfo staffInfoData = new StaffInfo();
                BeanUtils.copyProperties(newStaffInfo, staffInfoData);
                staffInfoData.setStatus(ProcessConstants.PERSON_APPROVING_STATUS);
                staffInfoData.setTaskId(null);
                staffInfoData.setComment("");
                staffInfoData.setTargetNodeTitle("");
                staffInfoData.setTargetMemberId("");
                staffInfoData.setUpdateTime(null);
                for (IntermediateNode newIntermediateNode : tempIntermediateNodes) {
                    if (newIntermediateNode.getNodeId().equals(newStaffInfo.getIdNode())) {
                        staffInfoData.setNodeInfoId(newIntermediateNode.getId());
                    }
                }
                for (Task backTask : taskList) {
                    if (String.valueOf(newStaffInfo.getMemberId()).equals(backTask.getAssignee())) {
                        staffInfoData.setTaskId(backTask.getId());
                    }
                }
                newStaffInfoData.add(staffInfoData);
            }
        }
        workflowNodeExtService.saveBatch(newStaffInfoData);
        if (!ObjectUtils.validateCollectionIsEmpty(backNodeMemberIds)) {
            List<Integer> memberIds = new ArrayList<>(backNodeMemberIds);
            imcComponent.imcAssistantSender(
                    messageContentWrapper.generateNotCommentMessageBody(MsgContentEnum.MESSAGE_BACK_CONTENT, task.getProcessInstanceId()),
                    RequestUserUtils.getUser().getId(),
                    memberIds, null);
        }
        if (ObjectUtils.isNotEmpty(backReq.getAtPersons())) {
            Result<MemberResp> memberById = memberFeignWrapper.getMemberById(RequestUserUtils.getUser().getMemberId());
            imcComponent.imcAssistantSender(
                    messageContentWrapper.generateCommentMessageBody(MsgContentEnum.MESSAGE_COMMENT_CONTENT, task.getProcessInstanceId(), memberById.getData().getName()),
                    RequestUserUtils.getUser().getId(), backReq.getAtPersons(), null
            );
            workflowProcessRelationsService.save(ProcessRelations.builder().processInstanceId(task.getProcessInstanceId()).userIds(StringUtils.join(backReq.getAtPersons(), LanguageExpressionConstants.LANGUAGE_COMMA)).build());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void readTask(ReadReq readReq) {
        Integer memberId = RequestUserUtils.getUser().getMemberId();
        String[] processInstanceIds = readReq.getProcessInstanceIds();
        if (ObjectUtils.isNotEmpty(processInstanceIds)) {
            workflowNodeExtService.updateCcReadStatusByStatus(processInstanceIds, memberId);
        }
    }

    @Override
    public Result<List<TaskListVo>> getTaskDone(ListQuery queryVo) {
        String memberId = String.valueOf(RequestUserUtils.getUser().getMemberId());
        Integer pageSize = queryVo.getPageSize();
        Integer pageNo = queryVo.getPageNo();
        IPage<StaffInfo> staffInfoIPage =
                workflowNodeExtService.selectDuplicatePage(memberId, pageSize, pageNo, queryVo.getKeyword(), queryVo.getIsUnread(), ProcessDefinitionConstants.CHECK_NODE);
        List<StaffInfo> records = staffInfoIPage.getRecords();
        long size = 0;
        List<TaskListVo> taskListVOList = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(records)) {
            Set<String> recordSet = new HashSet<>();
            if (ObjectUtils.isNotEmpty(records)) {
                for (StaffInfo record : records) {
                    recordSet.add(record.getProcessInstanceId());
                }
            }
            size = staffInfoIPage.getTotal();
            processListData(recordSet, taskListVOList, null);
        }
        return Result.build(taskListVOList, size);
    }

    @Override
    public Result<List<TaskListVo>> listCcToMe(ListQuery queryVo) {
        String memberId = String.valueOf(RequestUserUtils.getUser().getMemberId());
        Integer pageSize = queryVo.getPageSize();
        Integer pageNo = queryVo.getPageNo();
        IPage<StaffInfo> staffInfoIPage =
                workflowNodeExtService.selectDuplicatePage(memberId, pageSize, pageNo, queryVo.getKeyword(), queryVo.getIsUnread(), ProcessDefinitionConstants.DUPLICATE_NODE);
        List<StaffInfo> records = staffInfoIPage.getRecords();
        long size = 0;
        List<TaskListVo> taskListVos = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(records)) {
            Map<String, Integer> nodeProcessIdAndReadStatus = new HashMap<>();
            if (ObjectUtils.isNotEmpty(records)) {
                for (StaffInfo record : records) {
                    nodeProcessIdAndReadStatus.put(record.getProcessInstanceId(), record.getReadStatus());
                }
            }
            size = staffInfoIPage.getTotal();
            processListData(nodeProcessIdAndReadStatus.keySet(), taskListVos, nodeProcessIdAndReadStatus);
        }
        return Result.build(taskListVos, size);
    }

    @Override
    public Result<List<TaskListVo>> getToDoList(ListQuery queryVo) {
        RequestUser user = RequestUserUtils.getUser();
        String memberId = String.valueOf(user.getMemberId());
        Integer pageSize = queryVo.getPageSize();
        Integer pageNo = queryVo.getPageNo();
        Map<String, Object> requestParameter = new HashMap<>();
        requestParameter.put("memberId", memberId);
        requestParameter.put("keyword", StringUtils.isNotEmpty(queryVo.getKeyword()) ? queryVo.getKeyword() : null);
        requestParameter.put("pageNo", ObjectUtils.isNotEmpty(pageNo) ? pageNo * pageSize : null);
        requestParameter.put("pageSize", ObjectUtils.isNotEmpty(pageSize) ? pageSize : null);
        List<String> records = approvalNodeMapper.queryToDoList(requestParameter);
        List<TaskListVo> taskListVOList = new ArrayList<>();
        long size = approvalNodeMapper.countToDoList(requestParameter);
        if (ObjectUtils.isNotEmpty(records)) {
            Set<String> recordSet = new HashSet<>();
            if (ObjectUtils.isNotEmpty(records)) {
                recordSet.addAll(records);
            }
            processListData(recordSet, taskListVOList, null);
        }
        return Result.build(taskListVOList, size);
    }

    @Override
    public Integer countToDoList() {
        RequestUser user = RequestUserUtils.getUser();
        Map<String, Object> requestParam = new HashMap<>();
        requestParam.put("memberId", user.getMemberId());
        return approvalNodeMapper.countToDoList(requestParam);
    }

    @Override
    public void markAllRead() {
        workflowNodeExtService.markAllRead(RequestUserUtils.getUser().getMemberId());
    }

    @Override
    public void urgeToApprove(UrgeToApproveReq urgeToApprove) {
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(urgeToApprove.getProcessInstanceId()).list();
        List<Integer> memberIds = new ArrayList<>();
        for (Task task : tasks) {
            if (ObjectUtils.isNotEmpty(task.getAssignee())) {
                memberIds.add(Integer.valueOf(task.getAssignee()));
            }
        }
        if (!io.jsonwebtoken.lang.Collections.isEmpty(memberIds)) {
            List<MemberDetailsResp> memberDetailsResps = memberFeignWrapper.queryMemberDetailList(memberIds);
            List<Integer> userIds = new ArrayList<>();
            for (MemberDetailsResp memberDetailsResp : memberDetailsResps) {
                userIds.add(memberDetailsResp.getUserId());
            }
            imcComponent.imcAssistantSender(
                    messageContentWrapper.generateNotCommentMessageBody(MsgContentEnum.MESSAGE_URGENT_CONTENT, urgeToApprove.getProcessInstanceId()),
                    RequestUserUtils.getUser().getId(), userIds, null);
        }
    }

    @Override
    public void updateTaskFormData(TaskFormDataReq taskFormDataReq) {
        FormData formData = workflowFormDataService.selectFormDataByProcessInstanceId(taskFormDataReq.getProcessInstanceId());
        if (ObjectUtils.isEmpty(formData)) {
            approvalNodeMapper.updateTaskFormData(taskFormDataReq.getProcessInstanceId(), taskFormDataReq.getFormData());
        } else {
            workflowFormDataService.updateFormDataByProcessInstanceId(taskFormDataReq.getProcessInstanceId(), taskFormDataReq.getFormData());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addSignTask(AddSignReq addSignReq) {
        Integer memberId = RequestUserUtils.getUser().getMemberId();
        TaskEntityImpl taskEntity = (TaskEntityImpl) taskService.createTaskQuery().taskId(addSignReq.getTaskId()).singleResult();
        String parentTaskId = taskEntity.getParentTaskId();
        if (StringUtils.isBlank(parentTaskId)) {
            taskEntity.setOwner(String.valueOf(memberId));
            taskEntity.setAssignee(null);
            taskEntity.setCountEnabled(true);
            taskService.saveTask(taskEntity);
        }
        List<TaskEntity> signSubTasks = createSignSubTasks(addSignReq, taskEntity);
        if (!ObjectUtils.validateCollectionIsEmpty(signSubTasks)) {
            modifyAddSignNodeInfo(addSignReq, taskEntity, signSubTasks);
        }
    }

    /**
     * 修改加签节点信息
     */
    private void modifyAddSignNodeInfo(AddSignReq addSignReq, TaskEntity taskEntity, List<TaskEntity> signSubTasks) {
        Boolean flag = addSignReq.getIsAfter();
        Integer status = flag ? ProcessConstants.PERSON_APPROVED_STATUS : ProcessConstants.PERSON_APPROVING_STATUS;
        StaffInfo staffInfo = new StaffInfo();
        staffInfo.setProcessInstanceId(taskEntity.getProcessInstanceId());
        staffInfo.setMemberId(RequestUserUtils.getUser().getMemberId());
        staffInfo.setIdNode(taskEntity.getTaskDefinitionKey());
        staffInfo.setComment(addSignReq.getMessage());
        staffInfo.setTaskId(operatorTaskEntity.getId());
        staffInfo.setStatus(status);
        workflowNodeExtService.updateNodeExtByProcessInstanceIdAndNodeId(staffInfo);
        StaffInfo operationStaffInfo = new StaffInfo();
        operationStaffInfo.setProcessInstanceId(taskEntity.getProcessInstanceId());
        operationStaffInfo.setMemberId(RequestUserUtils.getUser().getMemberId());
        operationStaffInfo.setIdNode(taskEntity.getTaskDefinitionKey());
        StaffInfo operationStaff = workflowNodeExtService.selectPersonalNode(operationStaffInfo);
        List<StaffInfo> staffInfoList = new ArrayList<>();
        StaffInfo staffInfoTem;
        List<Integer> signPersons = new ArrayList<>();
        for (TaskEntity signSubTask : signSubTasks) {
            signPersons.add(Integer.valueOf(signSubTask.getAssignee()));
        }
        List<MemberDetailsResp> memberDetailsResps = memberFeignWrapper.queryMemberDetailList(signPersons);
        for (TaskEntity signSubTask : signSubTasks) {
            for (MemberDetailsResp signPerson : memberDetailsResps) {
                if (signPerson.getMemberId().equals(Integer.valueOf(signSubTask.getAssignee()))) {
                    staffInfoTem = taskEntityToStaffInfoConverter(signSubTask, signPerson, operationStaff, flag);
                    staffInfoList.add(staffInfoTem);
                    break;
                }
            }
        }
        if (ObjectUtils.isNotEmpty(staffInfoList)) {
            workflowNodeExtService.saveBatch(staffInfoList);
        }
        imcComponent.imcAssistantSender(
                messageContentWrapper.generateNotCommentMessageBody(MsgContentEnum.MESSAGE_AUDIT_CONTENT, taskEntity.getProcessInstanceId()),
                RequestUserUtils.getUser().getId(),
                signPersons, null);
    }

    private StaffInfo taskEntityToStaffInfoConverter(TaskEntity signSubTask, MemberDetailsResp signPerson, StaffInfo operationStaff, boolean isAfter) {
        StaffInfo staffInfoTem = new StaffInfo();
        staffInfoTem.setMemberName(signPerson.getMemberName());
        staffInfoTem.setMemberId(signPerson.getMemberId());
        staffInfoTem.setUserId(signPerson.getUserId());
        staffInfoTem.setUrl(signPerson.getAvatar());
        staffInfoTem.setIdNode(signSubTask.getTaskDefinitionKey());
        staffInfoTem.setTypeNode(ProcessDefinitionConstants.CHECK_NODE);
        staffInfoTem.setProcessName(operationStaff.getProcessName());
        staffInfoTem.setStarterName(operationStaff.getStarterName());
        if (isAfter) {
            staffInfoTem.setCreateTime(operationStaff.getCreateTime().minusHours(1));
        } else {
            staffInfoTem.setCreateTime(operationStaff.getCreateTime().plusHours(1));
        }
        staffInfoTem.setTaskId(signSubTask.getId());
        staffInfoTem.setProcessInstanceId(signSubTask.getProcessInstanceId());
        staffInfoTem.setStatus(ProcessConstants.PERSON_APPROVING_STATUS);
        staffInfoTem.setUpdateTime(null);
        return staffInfoTem;
    }

    /**
     * 创建加签子任务
     *
     * @param addSignReq 加签参数
     * @param taskEntity 父任务
     */
    private List<TaskEntity> createSignSubTasks(AddSignReq addSignReq, TaskEntity taskEntity) {
        Integer memberId = RequestUserUtils.getUser().getMemberId();
        List<TaskEntity> taskEntities = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(addSignReq.getSignPersons())) {
            String parentTaskId = taskEntity.getParentTaskId();
            if (StringUtils.isBlank(parentTaskId)) {
                parentTaskId = taskEntity.getId();
            }
            String finalParentTaskId = parentTaskId;
            List<StaffInfo> staffInfos = workflowNodeExtService.selectListByProcessInstanceIdAndNodeId(taskEntity.getProcessInstanceId(), Collections.singletonList(taskEntity.getTaskDefinitionKey()));
            //1.创建被加签人的任务列表
            List<Integer> signPersons = addSignReq.getSignPersons();
            Set<Integer> signPersonsSet = new HashSet<>();
            for (Integer signPerson : signPersons) {
                boolean personFlag = false;
                for (StaffInfo staffInfo : staffInfos) {
                    if (staffInfo.getMemberId().equals(signPerson)) {
                        personFlag = true;
                        break;
                    }
                }
                if (!personFlag) {
                    signPersonsSet.add(signPerson);
                }
            }
            if (ObjectUtils.isEmpty(signPersonsSet)) {
                return null;
            }
            for (Integer signPerson : signPersonsSet) {
                TaskEntity subTask = createSubTask(taskEntity, finalParentTaskId, String.valueOf(signPerson));
                taskEntities.add(subTask);
            }
            String taskId = taskEntity.getId();
            if (StringUtils.isBlank(taskEntity.getParentTaskId())) {
                //2.创建加签人的任务并执行完毕
                operatorTaskEntity = createSubTask(taskEntity, finalParentTaskId, String.valueOf(memberId));
                taskId = operatorTaskEntity.getId();
            }
            Task taskInfo = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (null != taskInfo && addSignReq.getIsAfter()) {
                taskService.complete(taskId);
            }
            //如果是候选人，需要删除运行时候选表种的数据。
            long candidateCount = taskService.createTaskQuery().taskId(parentTaskId).taskCandidateUser(String.valueOf(memberId)).count();
            if (candidateCount > 0) {
                taskService.deleteCandidateUser(parentTaskId, String.valueOf(memberId));
            }
        }
        return taskEntities;
    }

    /**
     * 创建子任务
     *
     * @param taskEntity 创建子任务
     * @param assignee   子任务的执行人
     */
    protected TaskEntity createSubTask(TaskEntity taskEntity, String taskId, String assignee) {
        TaskEntity task = (TaskEntity) taskService.newTask();
        task.setCategory(taskEntity.getCategory());
        task.setDescription(taskEntity.getDescription());
        task.setTenantId(taskEntity.getTenantId());
        task.setOwner(assignee);
        task.setAssignee(assignee);
        task.setName(taskEntity.getName());
        task.setParentTaskId(taskId);
        task.setProcessDefinitionId(taskEntity.getProcessDefinitionId());
        task.setProcessInstanceId(taskEntity.getProcessInstanceId());
        task.setTaskDefinitionKey(taskEntity.getTaskDefinitionKey());
        task.setTaskDefinitionId(taskEntity.getTaskDefinitionId());
        task.setPriority(taskEntity.getPriority());
        task.setCreateTime(new Date());
        taskService.saveTask(task);
        return task;
    }

    private StaffInfo getStaffUpdateInfo(String processInstanceId, Integer status, String memberId, String activityId, String comment) {
        StaffInfo staffInfo = new StaffInfo();
        staffInfo.setProcessInstanceId(processInstanceId);
        staffInfo.setStatus(status);
        staffInfo.setMemberId(Integer.valueOf(memberId));
        staffInfo.setIdNode(activityId);
        staffInfo.setComment(comment);
        return staffInfo;
    }

    private StaffInfo getStaffSaveInfo(String processInstanceId, Integer status, String memberId, String comment) {
        StaffInfo staffInfo = new StaffInfo();
        staffInfo.setProcessInstanceId(processInstanceId);
        staffInfo.setStatus(status);
        staffInfo.setMemberId(Integer.valueOf(memberId));
        staffInfo.setIdNode(ProcessDefinitionConstants.REPEAL_NODE);
        staffInfo.setTypeNode(ProcessDefinitionConstants.REPEAL_NODE);
        staffInfo.setComment(comment);
        staffInfo.setUpdateTime(LocalDateTime.now());
        return staffInfo;
    }

    private IntermediateNode getIntermediateRepealNodeInfo(String processInstanceId) {
        IntermediateNode intermediateNode = new IntermediateNode();
        intermediateNode.setProcessInstanceId(processInstanceId);
        intermediateNode.setNodeId(ProcessDefinitionConstants.REPEAL_NODE);
        intermediateNode.setNodeType(ProcessDefinitionConstants.REPEAL_NODE);
        intermediateNode.setNodeTitle(ProcessDefinitionConstants.REPEAL_NODE_NAME);
        intermediateNode.setIsArrive(ProcessConstants.NODE_ARRIVED_STATUS);
        intermediateNode.setUpdateTime(LocalDateTime.now());
        int nodeNums = workflowNodeInfoService.queryProcessNodesNum(processInstanceId);
        intermediateNode.setSort(nodeNums);
        return intermediateNode;
    }

    private void saveApproveAttachments(List<DictionaryVo> dictionaryVOList, String processInstanceId, String nodeId) {
        List<Dictionary> dictionaries = BeanUtilsExt.copyObjectListProperties(dictionaryVOList, Dictionary.class);
        for (Dictionary dictionary : dictionaries) {
            dictionary.setCreateUser(RequestUserUtils.getUser().getMemberId());
            dictionary.setCode(nodeId);
            dictionary.setBelongTo(ProcessConstants.ATTACHMENT_BELONG_TO_APPROVAL);
            dictionary.setProcessInstanceId(processInstanceId);
            dictionary.setCompanyId(RequestUserUtils.getUser().getCompanyId());
        }
        workflowDictionaryService.saveBatch(dictionaries);
    }

    private Result<?> processDelegateAndTransfer(DelegateReq delegateReq, Integer operationType) {
        String taskId = delegateReq.getTaskId();
        String assignee = String.valueOf(delegateReq.getMemberId());
        String memberId = String.valueOf(RequestUserUtils.getUser().getMemberId());
        Task task = permissionService.validateDelegatePermissionOnTask(taskId, memberId, assignee);
        MemberDetailsResp memberDetailsResp = memberFeign.queryMemberById(Integer.valueOf(assignee));
        StaffInfo staffInfo = new StaffInfo();
        staffInfo.setProcessInstanceId(task.getProcessInstanceId());
        staffInfo.setIdNode(task.getTaskDefinitionKey());
        staffInfo.setMemberId(Integer.valueOf(assignee));
        staffInfo.setStatus(ProcessConstants.PERSON_APPROVING_STATUS);
        StaffInfo currentApproving = workflowNodeExtService.selectPersonalNodeApprovingNum(staffInfo);
        if (ObjectUtils.isEmpty(currentApproving)) {
            createNewNodeExt(RequestUserUtils.getUser().getMemberId(), task.getProcessInstanceId(), task.getTaskDefinitionKey(), delegateReq.getMemberId(), memberDetailsResp.getUserId(), memberDetailsResp.getMemberName());
        } else {
            if (ObjectUtils.isNotEmpty(currentApproving.getTaskId())) {
                taskService.complete(currentApproving.getTaskId());
            }
            StaffInfo oldStaffInfo = new StaffInfo();
            oldStaffInfo.setMemberId(RequestUserUtils.getUser().getMemberId());
            oldStaffInfo.setProcessInstanceId(task.getProcessInstanceId());
            oldStaffInfo.setIdNode(task.getTaskDefinitionKey());
            oldStaffInfo.setTaskId(task.getId());
            workflowNodeExtService.updateNodeExtByProcessInstanceIdAndNodeId(oldStaffInfo);
        }
        taskService.delegateTask(task.getId(), assignee);
        if (ProcessConstants.PERSON_TRANSFER_STATUS.equals(operationType)) {
            taskService.setOwner(task.getId(), assignee);
            processNodeExtData(delegateReq.getMessage(), task, ProcessConstants.PERSON_TRANSFER_STATUS, assignee, true);
        }
        if (ProcessConstants.PERSON_DELEGATE_STATUS.equals(operationType)) {
            taskService.setOwner(task.getId(), memberId);
            processNodeExtData(delegateReq.getMessage(), task, ProcessConstants.PERSON_DELEGATE_STATUS, assignee, true);
        }
        if (!ObjectUtils.validateCollectionIsEmpty(delegateReq.getDictionaryVOList())) {
            saveApproveAttachments(delegateReq.getDictionaryVOList(), task.getProcessInstanceId(), task.getTaskDefinitionKey());
        }
        imcComponent.imcAssistantSender(
                messageContentWrapper.generateNotCommentMessageBody(MsgContentEnum.MESSAGE_AUDIT_CONTENT, task.getProcessInstanceId()),
                RequestUserUtils.getUser().getId(),
                Collections.singletonList(memberDetailsResp.getUserId()), null);
        if (ObjectUtils.isNotEmpty(delegateReq.getAtPersons())) {
            Result<MemberResp> memberById = memberFeignWrapper.getMemberById(RequestUserUtils.getUser().getMemberId());
            imcComponent.imcAssistantSender(
                    messageContentWrapper.generateCommentMessageBody(MsgContentEnum.MESSAGE_COMMENT_CONTENT, task.getProcessInstanceId(), memberById.getData().getName()),
                    RequestUserUtils.getUser().getId(), delegateReq.getAtPersons(), null
            );
            workflowProcessRelationsService.save(ProcessRelations.builder().processInstanceId(task.getProcessInstanceId()).userIds(StringUtils.join(delegateReq.getAtPersons(), LanguageExpressionConstants.LANGUAGE_COMMA)).build());
        }
        return Result.build();
    }

    private void createNewNodeExt(Integer operationMemberId, String processInstanceId, String nodeId, Integer targetMemberId, Integer targetUserId, String targetMemberName) {
        // 获取操作人当前节点的数据
        StaffInfo staffInfo = new StaffInfo();
        staffInfo.setMemberId(operationMemberId);
        staffInfo.setProcessInstanceId(processInstanceId);
        staffInfo.setIdNode(nodeId);
        StaffInfo operationStaffInfo = workflowNodeExtService.selectPersonalNode(staffInfo);
        StaffInfo newStaffInfo = new StaffInfo();
        BeanUtils.copyProperties(operationStaffInfo, newStaffInfo);
        newStaffInfo.setUserId(targetUserId);
        newStaffInfo.setMemberId(targetMemberId);
        newStaffInfo.setStatus(ProcessConstants.PROCESS_APPROVING_STATUS);
        newStaffInfo.setMemberName(targetMemberName);
        newStaffInfo.setCreateTime(LocalDateTime.now());
        newStaffInfo.setComment("");
        newStaffInfo.setTargetMemberId("");
        newStaffInfo.setTargetNodeTitle("");
        newStaffInfo.setUpdateTime(null);
        // 保存被操作人的操作节点信息
        workflowNodeExtService.save(newStaffInfo);
    }

    private void processListData(Set<String> recordSet, List<TaskListVo> taskListVOList, Map<String, Integer> nodeProcessIdAndReadStatus) {
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
        List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.processInstanceIds(recordSet).orderByProcessInstanceStartTime().desc().list();
        Set<String> processInstanceIds = new HashSet<>();
        for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
            processInstanceIds.add(historicProcessInstance.getId());
        }
        List<ProcessInstanceStatus> processInstanceStatuses = workflowProcessStatusService.selectProcessesStatus(processInstanceIds);
        if (ObjectUtils.isNotEmpty(processInstanceStatuses)) {
            List<Integer> memberIds = new ArrayList<>();
            for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
                memberIds.add(Integer.valueOf(historicProcessInstance.getStartUserId()));
            }
            List<MemberDetailsResp> memberDetailsResps = memberFeignWrapper.queryMemberDetailList(memberIds);
            for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
                TaskListVo taskListVO = new TaskListVo();
                taskListVO.setTaskName(historicProcessInstance.getName());
                taskListVO.setProcessName(historicProcessInstance.getName());
                taskListVO.setProcessInstanceId(historicProcessInstance.getId());
                taskListVO.setEndTime(historicProcessInstance.getEndTime() != null ? LocalDateTime.ofInstant(historicProcessInstance.getEndTime().toInstant(), ZoneId.systemDefault()) : null);
                taskListVO.setStarTime(historicProcessInstance.getStartTime() != null ? LocalDateTime.ofInstant(historicProcessInstance.getStartTime().toInstant(), ZoneId.systemDefault()) : null);
                MemberInfoVo memberResp = null;
                if (ObjectUtils.isNotEmpty(memberDetailsResps)) {
                    for (MemberDetailsResp memberDetailsResp : memberDetailsResps) {
                        if (memberDetailsResp.getMemberId().equals(Integer.valueOf(historicProcessInstance.getStartUserId()))) {
                            memberResp = MemberInfoVo.builder()
                                    .url(memberDetailsResp.getAvatar())
                                    .name(memberDetailsResp.getMemberName())
                                    .phone(memberDetailsResp.getPhone())
                                    .id(memberDetailsResp.getMemberId())
                                    .build();
                        }
                    }
                }
                taskListVO.setMemberResp(memberResp);
                // 获取流程的审批状态
                for (ProcessInstanceStatus processInstanceStatus : processInstanceStatuses) {
                    if (processInstanceStatus.getProcessInstanceId().equals(historicProcessInstance.getId())) {
                        taskListVO.setStatus(processInstanceStatus.getStatus());
                    }
                }
                // 获取任务的读取状态
                if (null != nodeProcessIdAndReadStatus) {
                    taskListVO.setReadStatus(nodeProcessIdAndReadStatus.get(historicProcessInstance.getId()));
                }
                taskListVOList.add(taskListVO);
            }
        }
    }
}